#include "readCard.h"

static uint32_t _g_head = 0;                      // 队列头部
static uint32_t _g_tail = 0;                      // 队列尾部
static READCARD_CARD _g_card[READCARD_MAX] = {0}; // 消息队列
static uint8_t _g_cache[READCARD_LENGTH] = {0};   // 数据缓存

/**
 * @name 接收数据
 * @description
 * @function
 * @returns {READCARD_CARD} 数据
 * @requires []
 */
static READCARD_CARD _readCard_recv(void) {
    uint8_t i, xor = 0;
    READCARD_CARD card = {0};
    // 校验头尾
    if (_g_cache[0] != READCARD_HEADER || _g_cache[READCARD_LENGTH - 1] != READCARD_TAIL)
        return card;
    // 数据异或
    for (i = 1; i < 7; ++i)
        xor ^= _g_cache[i];
    // 校验异或
    if (_g_cache[READCARD_LENGTH - 2] != xor)
        return card;
    // 解析数据
    card.cardType = _g_cache[2];
    card.cardID = _g_cache[3] << 24 | _g_cache[4] << 16 | _g_cache[5] << 8 | _g_cache[6];
    // 清空缓存
    for (i = 0; i < READCARD_LENGTH; ++i)
        _g_cache[i] = 0;
    // 返回数据
    return card;
}

/**
 * @name USART中断
 * @description
 * @function
 * @returns {void}
 * @requires []
 */
void READCARD_USART_IRQHandler(void) {
    uint8_t i;
    READCARD_CARD card;
    // 数据就绪
    if (USART_GetITStatus(READCARD_USART, USART_IT_RXNE) == SET) {
        // 前移一位
        for (i = 1; i < READCARD_LENGTH; ++i)
            _g_cache[i - 1] = _g_cache[i];
        // 读取数据
        _g_cache[READCARD_LENGTH - 1] = USART_ReceiveData(READCARD_USART);
        // 接收完毕
        if ((card = _readCard_recv()).cardType) {
            // 队列已满
            if ((_g_tail + 1) % READCARD_MAX == _g_head) {
                ++_g_head;
                if (_g_head == READCARD_MAX)
                    _g_head = 0;
            }
            // 插入队列
            _g_card[_g_tail++] = card;
            if (_g_tail == READCARD_MAX)
                _g_tail = 0;
        }
        // 清除标志
        USART_ClearITPendingBit(READCARD_USART, USART_IT_RXNE);
    }
}

/**
 * @name readCard初始化
 * @description
 * @function
 * @returns {void}
 * @requires []
 */
void readCard_init(void) {
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    NVIC_InitTypeDef NVIC_InitStruct = {0};
    USART_InitTypeDef USART_InitStruct = {0};
    // 使能时钟
    READCARD_RCC_AHBPeriphClockCmd;
    // 配置GPIO
    GPIO_InitStruct.GPIO_Pin = READCARD_GPIO_Pin;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
    // 初始GPIO
    GPIO_Init(READCARD_GPIO, &GPIO_InitStruct);
    // 配置复用
    GPIO_PinAFConfig(READCARD_GPIO, READCARD_USART_RX, READCARD_GPIO_AF_USART);
    // 使能时钟
    READCARD_RCC_APBPeriphClockCmd;
    // 配置USART
    USART_InitStruct.USART_BaudRate = READCARD_USART_BaudRate;
    USART_InitStruct.USART_WordLength = USART_WordLength_8b;
    USART_InitStruct.USART_StopBits = USART_StopBits_1;
    USART_InitStruct.USART_Parity = USART_Parity_No;
    USART_InitStruct.USART_Mode = USART_Mode_Rx;
    USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    // 初始USART
    USART_Init(READCARD_USART, &USART_InitStruct);
    // 优先分组
    SYS_NVIC_PriorityGroupConfig;
    // 配置中断
    USART_ITConfig(READCARD_USART, USART_IT_RXNE, ENABLE);
    NVIC_InitStruct.NVIC_IRQChannel = READCARD_USART_IRQn;
    NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = READCARD_NVIC_IRQChannelPreemptionPriority;
    NVIC_InitStruct.NVIC_IRQChannelSubPriority = READCARD_NVIC_IRQChannelSubPriority;
    NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
    // 初始中断
    NVIC_Init(&NVIC_InitStruct);
    // 使能USART
    USART_Cmd(READCARD_USART, ENABLE);
}

/**
 * @name 接收数据
 * @description
 * @function
 * @returns {READCARD_CARD} 数据
 * @requires []
 */
READCARD_CARD readCard_recv(void) {
    READCARD_CARD card = {0};
    // 移出队列
    if (_g_head != _g_tail)
        card = _g_card[_g_head++];
    if (_g_head == READCARD_MAX)
        _g_head = 0;
    // 返回数据
    return card;
}
